package com.tencreat.service.mall.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tencreat.common.core.HttpResult;
import com.tencreat.common.core.domain.model.LoginUser;
import com.tencreat.common.core.domain.model.ReqIdParam;
import com.tencreat.common.core.domain.model.ReqIdsParam;
import com.tencreat.common.core.domain.model.ReqStringParam;
import com.tencreat.common.enums.*;
import com.tencreat.common.enums.account.PayCompanyEnum;
import com.tencreat.common.enums.mall.AllEnum;
import com.tencreat.common.exception.CustomException;
import com.tencreat.common.utils.RabbitSendUtils;
import com.tencreat.common.utils.SecurityUtils;
import com.tencreat.common.utils.TenCreatUtil;
import com.tencreat.domain.account.MallUser;
import com.tencreat.domain.account.vo.AccountRechargeRecordVo;
import com.tencreat.domain.mall.*;
import com.tencreat.domain.mall.dto.BalanceRecordDTO;
import com.tencreat.domain.mall.dto.RechargeOrderDTO;
import com.tencreat.domain.mall.vo.BalanceChangeVO;
import com.tencreat.domain.mall.vo.IntegralStatisticsVO;
import com.tencreat.domain.mall.vo.ResBalanceRecordVO;
import com.tencreat.domain.mall.vo.ResMyPurseInfoVO;
import com.tencreat.mapper.mall.GoodsRollOrderMapper;
import com.tencreat.mapper.mall.RechargeOrderMapper;
import com.tencreat.service.account.IMallUserService;
import com.tencreat.service.mall.IMallOrderService;
import com.tencreat.service.mall.IPayService;
import com.tencreat.service.mall.IRechargeOrderService;
import com.tencreat.service.pay.TradeService;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;


/**
 * 充值(提现)订单Service业务层处理
 *
 * @author wangkai
 * @date 2021-11-13
 */
@Service("rechargeOrderService")
@Slf4j
public class RechargeOrderServiceImpl extends ServiceImpl<RechargeOrderMapper, RechargeOrder> implements IRechargeOrderService {
    private final static Logger logger = LoggerFactory.getLogger("sys-pay");
    @Autowired
    private IRechargeOrderService rechargeOrderService;//充值提现

    @Autowired
    private IPayService iPayService;

    @Autowired
    private IMallOrderService mallOrderService;//订单Service

    @Autowired
    private IMallUserService userService;//用户Service
    @Resource
    private RabbitSendUtils rabbitUtils;

    @Autowired
    private GoodsRollOrderMapper goodsRollOrderMapper;


    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    /**
     * 查询充值(提现)订单
     *
     * @param orderId 充值(提现)订单ID
     * @return 充值(提现)订单
     */
    @Override
    public RechargeOrder selectRechargeOrderById(ReqIdParam orderId) {
        return baseMapper.selectById(orderId.getId());
    }

    /**
     * 查询充值(提现)订单列表
     *
     * @param rechargeOrder 充值(提现)订单
     * @return 充值(提现)订单
     */
    @Override
    public List<RechargeOrder> selectRechargeOrderList(RechargeOrder rechargeOrder) {
        return baseMapper.selectList(Wrappers.query(rechargeOrder));
    }

    /**
     * 新增充值(提现)订单
     *
     * @param rechargeOrder 充值(提现)订单
     * @return 结果
     */
    @Override
    public int insertRechargeOrder(RechargeOrder rechargeOrder) {
        rechargeOrder.setCreateTime(LocalDateTime.now());
        return baseMapper.insert(rechargeOrder);
    }

    /**
     * 修改充值(提现)订单
     *
     * @param rechargeOrder 充值(提现)订单
     * @return 结果
     */
    @Override
    public int updateRechargeOrder(RechargeOrder rechargeOrder) {
        rechargeOrder.setUpdateTime(LocalDateTime.now());
        return baseMapper.updateById(rechargeOrder);
    }

    /**
     * 批量删除充值(提现)订单
     *
     * @param orderIds 需要删除的充值(提现)订单ID
     * @return 结果
     */
    @Override
    public int deleteRechargeOrderByIds(ReqIdsParam orderIds) {
        return baseMapper.deleteBatchIds(orderIds.getId());
    }

    /**
     * 删除充值(提现)订单信息
     *
     * @param orderId 充值(提现)订单ID
     * @return 结果
     */
    @Override
    public int deleteRechargeOrderById(ReqIdParam orderId) {
        return baseMapper.deleteById(orderId.getId());
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor = Exception.class)
    public HttpResult<?> recharge(RechargeOrderDTO vo, Long uuid, LoginUser loginCheck) throws Exception {
        logger.info("进入充值业务");
        ConcurrentHashMap<Object, Object> map = new ConcurrentHashMap<>();
        if (vo.getTradeAmount().compareTo(new BigDecimal("0.01")) < 0) {
            return HttpResult.error("最小代采购金额0.01");
        }
        //查到当前用户的代采购额度
        MallUser mallUser = userService.lambdaQuery().eq(MallUser::getUuid, uuid).one();
        //如果代采购额度小于充值金额
        if (mallUser.getRechargeLimit().compareTo(vo.getTradeAmount()) < 0) {
            return HttpResult.error("代采购额度不足");
        }

        //充值订单编号
        String sn = TenCreatUtil.getOrderNo();

        //存入充值订单表
        RechargeOrder ro = new RechargeOrder();
        ro.setOrderSn(sn);
        ro.setUuid(loginCheck.getAccountLogin().getUuid());
        ro.setOrderStatus(OrderStatus.PAY)
                .setTradeAmount(vo.getTradeAmount())
                .setOrderType(vo.getOrderType())
                .setDelFlag("0")
                .setConsumerRoll(vo.getConsumerRoll())
                .setGoodsRoll(vo.getGoodsRoll())
                .setCreateTime(LocalDateTime.now());
        rechargeOrderService.save(ro);


        MallOrder mallOrder = new MallOrder();
        mallOrder.setUuid(loginCheck.getAccountLogin().getUuid());
        mallOrder.setOrderSn(sn);
        mallOrder.setOrderType(vo.getOrderType());
        mallOrder.setStatusUser(UserOrderStatus.WAIT_PAY);
        mallOrder.setOrderStatus(OrderStatus.PAY);
        mallOrder.setOrderPrice(vo.getTradeAmount());
        mallOrder.setActualPrice(vo.getTradeAmount());
        mallOrder.setDelFlag("0");
        mallOrder.setCreateTime(LocalDateTime.now());
        mallOrder.setUpdateTime(LocalDateTime.now());
        mallOrder.setConsumerRoll(vo.getConsumerRoll());
        mallOrder.setGoodsRoll(vo.getGoodsRoll());
        mallOrderService.save(mallOrder);

        if (vo.getCompany() == PayCompanyEnum.PLATFORM && vo.getPayType() == PayType.WX_PAY) {
            log.info("进入微信支付...");
            ReqStringParam param = new ReqStringParam();
            param.setCommon(sn);
            param.setTradeType(vo.getTradeType());
            map.put("payInfo", iPayService.createWxOrder(param));
            map.put("orderSn", sn);
            return HttpResult.ok(map);
        } else if (vo.getCompany() == PayCompanyEnum.PLATFORM && vo.getPayType() == PayType.ALI_PAY) {
            log.info("进入支付宝支付...");
            ReqStringParam param = new ReqStringParam();
            param.setCommon(sn);
            map.put("payInfo", iPayService.createAliPayOrder(param));
            map.put("orderSn", sn);
            return HttpResult.ok(map);
        }
        // 杉德宝银行卡快捷支付
        else if (vo.getCompany() == PayCompanyEnum.SHAN_DE_BAO && vo.getPayType() == PayType.FAST_PAYMENT) {
            log.info("进入杉德宝快捷支付...");
            //map.put("payInfo", iPayService.sandPayCreateOrderBank(sn));
            ReqStringParam param2 = new ReqStringParam();
            param2.setCommon(sn);
            param2.setBandCartId(vo.getBandCartId());
            map.put("payInfo", iPayService.sandGetKaptcha(param2));
            map.put("orderSn", sn);
            return HttpResult.ok(map);
        } else {
            throw new CustomException("暂时不支持这个支付方式！");
        }
    }

    @Override
    public List<AccountRechargeRecordVo> rechargeRecordList(LoginUser loginCheck) {
        return null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public HttpResult<?> pcRecharge(Map<String, Object> map) {
        Long uuid = Long.valueOf(String.valueOf(map.get("uuid")));
        BigDecimal value = new BigDecimal(String.valueOf(map.get("value")));
        String type = String.valueOf(map.get("type"));
        String chargeType = String.valueOf(map.get("reChargeType"));
        String userType = String.valueOf(map.get("userType"));
        String remark = String.valueOf(map.get("remark"));

        MallUser user = userService.lambdaQuery().eq(MallUser::getUuid, uuid).one();

        //充值订单
        RechargeOrder ro = new RechargeOrder();

        //主订单
        MallOrder mallOrder = new MallOrder();

        //余额变动
        BalanceChange change = new BalanceChange();

        if (user == null) {
            return HttpResult.error("该用户id不存在," + uuid);
        }
        if ("1".equals(userType) && user.getSupplier() == 0) {
            return HttpResult.error("该用户不是供应商," + uuid);
        }
        if ("3".equals(userType) && user.getStore() == 0) {
            return HttpResult.error("该用户不是供应商," + uuid);
        }


        //如果扣除余额，检验值不大于本身余额
        if ("2".equals(type)) {
            if ("1".equals(chargeType)) {
                //如果是供应商,扣除供应商货款
                if ("1".equals(userType)) {
                    if (value.compareTo(user.getFinance()) > 0) {
                        return HttpResult.error(String.format("供应商余额不足,最多扣除 %s", user.getFinance()));
                    }
                }
                //如果是店铺,扣除店铺货款
                if ("3".equals(userType)) {
                    if (value.compareTo(user.getStoreFinance()) > 0) {
                        return HttpResult.error(String.format("店铺余额不足,最多扣除 %s", user.getStoreFinance()));
                    }
                }
            }
            if ("2".equals(chargeType) && value.compareTo(user.getConsumerRoll()) > 0) {
                return HttpResult.error(String.format("消费券不足,最多扣除 %s", user.getBalance()));
            }
            if ("3".equals(chargeType) && value.compareTo(user.getConsumerRoll()) > 0) {
                return HttpResult.error(String.format("提货单不足,最多扣除 %s", user.getBalance()));
            }
            if ("4".equals(chargeType) && value.compareTo(user.getRechargeLimit()) > 0) {
                return HttpResult.error(String.format("代采购额度不足,最多扣除 %s", user.getRechargeLimit()));
            }
            ro.setTradeAmount(value.negate());

            mallOrder.setOrderPrice(value.negate());
            mallOrder.setActualPrice(value.negate());

            user.setBalance(user.getBalance() == null ? BigDecimal.ZERO : user.getBalance().subtract(value));

            change.setChangAmount(value.negate());
        } else {
            ro.setTradeAmount(value);

            mallOrder.setOrderPrice(value);
            mallOrder.setActualPrice(value);

            user.setBalance(user.getBalance() == null ? value : user.getBalance().add(value));

            change.setChangAmount(value);
        }

        //充值订单编号
        String sn = TenCreatUtil.getOrderNo();

        ro.setOrderSn(sn);
        ro.setUuid(uuid);
        ro.setOrderStatus(OrderStatus.OK);
        ro.setOrderType(OrderType.RECHARGE)
                .setDelFlag("0")
                .setCreateTime(LocalDateTime.now());

        rechargeOrderService.save(ro);

        mallOrder.setUuid(uuid);
        mallOrder.setOrderSn(sn);
        mallOrder.setOrderType(OrderType.ACCOUNT_RECHARGE);
        mallOrder.setStatusUser(UserOrderStatus.OK);

        mallOrder.setDelFlag("0");
        mallOrder.setCreateTime(LocalDateTime.now());
        mallOrder.setUpdateTime(LocalDateTime.now());
        mallOrderService.save(mallOrder);

        // 余额充值|货款充值
        if ("1".equals(chargeType)) {
            //供应商货款
            if ("1".equals(userType)) {
                rabbitUtils.sendBalanceMessage(uuid, change.getChangAmount(), type, "2".equals(type) ? BalanceBusinessType.ACCOUNT_SUB : BalanceBusinessType.ACCOUNT_RECHARGE, remark, mallOrder.getOrderSn(), BalanceTypeEnum.FINANCE);
            }
            //店铺货款
            if ("3".equals(userType)) {
                rabbitUtils.sendBalanceMessage(uuid, change.getChangAmount(), type, "2".equals(type) ? BalanceBusinessType.ACCOUNT_SUB : BalanceBusinessType.ACCOUNT_RECHARGE, remark, mallOrder.getOrderSn(), BalanceTypeEnum.STORE_FINANCE);
            }
//            rabbitUtils.sendBalanceMessage(uuid, change.getChangAmount(), type, "2".equals(type) ? BalanceBusinessType.ACCOUNT_SUB : BalanceBusinessType.ACCOUNT_RECHARGE, "", mallOrder.getOrderSn(), BalanceTypeEnum.BALANCE);
        } else if ("2".equals(chargeType)) {
            // 消费券
            rabbitUtils.sendBalanceMessage(uuid, change.getChangAmount(), type, "2".equals(type) ? BalanceBusinessType.ACCOUNT_SUB : BalanceBusinessType.ACCOUNT_RECHARGE, remark, sn, BalanceTypeEnum.CONSUMER_ROLL);
        } else if ("3".equals(chargeType)) {
            // 提货单
            rabbitUtils.sendBalanceMessage(uuid, change.getChangAmount(), type, "2".equals(type) ? BalanceBusinessType.ACCOUNT_SUB : BalanceBusinessType.ACCOUNT_RECHARGE, remark, sn, BalanceTypeEnum.GOODS_ROLL);
        }else if ("4".equals(chargeType)){
            // 代采购额度
            rabbitUtils.sendBalanceMessage(uuid, change.getChangAmount(), type, "2".equals(type) ? BalanceBusinessType.ACCOUNT_SUB : BalanceBusinessType.ACCOUNT_RECHARGE, remark, sn, BalanceTypeEnum.RECHARGE_LIMIT_CHANGE);
        }

        return HttpResult.ok("充值成功");

    }


    @Override
    public Page<ResBalanceRecordVO> balanceRecordPage(IPage<ResBalanceRecordVO> page, BalanceRecordDTO params) {
        return baseMapper.balanceRecordPage(page, params);
    }

    @Override
    public ResMyPurseInfoVO getMyPurseInfo(Long uuid) {
        MallUser user = userService.lambdaQuery().eq(MallUser::getUuid, uuid).one();

        List<BalanceChangeVO> details = baseMapper.selectPurseDetail(uuid);

        return ResMyPurseInfoVO.builder()
                .balance(user.getBalance())
                .waitingBalance(user.getWaitingBalance())
                .purseDetailList(details)
                .build();
    }

    @Override
    public HttpResult<?> balanceValidation(ReqStringParam id, LoginUser loginCheck) {
        MallUser mallUser = userService.lambdaQuery().eq(MallUser::getUuid, loginCheck.getAccountLogin().getUuid()).one();
        if (StrUtil.isEmpty(mallUser.getPayPassword())) {
            throw new CustomException("你还未设置支付密码");
        }
        if (!mallUser.getPayPassword().equals(id.getCommon())) {
            return HttpResult.error("支付密码错误");
        }
        return HttpResult.ok();
    }

    @Override
    public IntegralStatisticsVO balanceStatistics(Integer balanceType) {
        // 已使用余额
        BigDecimal amountSub = baseMapper.queryAmountSub(balanceType);
        if (amountSub != null) {
            amountSub = amountSub.abs();
        }
        // 实时余额
        BigDecimal surplus = baseMapper.queryAmountSurplus(balanceType);
        // 总
        BigDecimal totalAdd = baseMapper.queryTotalAdd(balanceType);
        // 货款统计
        BigDecimal orderAdd = BigDecimal.ZERO;
        BigDecimal orderSub = BigDecimal.ZERO;
        BigDecimal orderConfirm = BigDecimal.ZERO;
        if (balanceType == 4 || balanceType == 5) {
            Long userId = SecurityUtils.getLoginUser().getUser().getUserId();
            if (userId == 1 || userId == 2) {
                userId = null;
            }

            surplus = baseMapper.queryAmountSurplusV2(balanceType, userId);
            // 订单收入
            orderAdd = baseMapper.queryTotalOrder(balanceType, BalanceBusinessType.ORDER_ADD, userId);
            orderConfirm = baseMapper.queryTotalOrder(balanceType, BalanceBusinessType.ORDER_CONFIRM, userId);
            orderSub = baseMapper.queryTotalOrder(balanceType, BalanceBusinessType.ORDER_SUB, userId);
        }

        IntegralStatisticsVO statisticsVO = new IntegralStatisticsVO();
        statisticsVO.setTotalSurplus(surplus);
        statisticsVO.setTotalSub(amountSub);
        statisticsVO.setTotalAdd(totalAdd);
        statisticsVO.setOrderAdd(orderAdd);
        statisticsVO.setOrderSub(orderSub.abs());
        statisticsVO.setOrderConfirm(orderConfirm.abs());

        return statisticsVO;
    }

    @Override
    public List<RechargePackage> getRechargePackageList() {

        return baseMapper.getRechargePackageList();
    }

    @Override
    public RechargePackage selectrRechargePackage(BigDecimal money) {
        RechargePackage rechargePackage = new RechargePackage();
        rechargePackage.setMoney(money);
        RechargePackage rechargePackage1 = baseMapper.selectrRechargePackage(money);
        if (rechargePackage1 != null) {
            return rechargePackage1;
        } else return rechargePackage;
    }


    @Override
    public IPage<GoodsRollOrder> goodsRollRecordPage(Page<GoodsRollOrder> page, BalanceRecordDTO params) {
        return baseMapper.goodsRollRecordPage(page, params);
    }

    @Override
    public HttpResult<GoodsRollOrder> updateGoodsRollRecord(GoodsRollOrder params) {

        // 0.
        GoodsRollOrder goodsRollOrder = goodsRollOrderMapper.selectById(params.getId());
        if (goodsRollOrder != null) {
            // 1. 改提货单记录的状态、修改时间
            goodsRollOrder.setStatus(1);
            goodsRollOrder.setUpdateTime(LocalDateTime.now());
            goodsRollOrder.setBalanceType(BalanceTypeEnum.GOODS_ROLL);
            goodsRollOrderMapper.updateById(goodsRollOrder);
            // 2.减待结算提货单 用队列
            rabbitUtils.sendBalanceMessage(goodsRollOrder.getUuid(), goodsRollOrder.getWaitGoodsRoll(), "2", goodsRollOrder.getBusinessType(), goodsRollOrder.getRemark(), goodsRollOrder.getSource(), BalanceTypeEnum.WAIT_GOODS_ROLL);
            // 3.加提货单
            rabbitUtils.sendBalanceMessage(goodsRollOrder.getUuid(), goodsRollOrder.getWaitGoodsRoll(), "1", goodsRollOrder.getBusinessType(), goodsRollOrder.getRemark(), goodsRollOrder.getSource(), BalanceTypeEnum.GOODS_ROLL);
        }

        return HttpResult.ok(goodsRollOrder);
    }

    @Override
    public BigDecimal rechargeAmount() {
        return baseMapper.rechargeAmount();
    }
}
